package dtm

import (
	"context"
	"database/sql"
	"fmt"

	"mall/common/resultx"
	"mall/service/backend/common/i18n"
	"mall/service/product/model"
	"mall/service/product/rpc/internal/svc"
	"mall/service/product/rpc/types/product"

	"github.com/dtm-labs/client/dtmgrpc"
	"github.com/sirupsen/logrus"
	"github.com/volatiletech/sqlboiler/v4/queries"
	"github.com/volatiletech/sqlboiler/v4/queries/qm"
	"github.com/zeromicro/go-zero/core/logx"
)

type UpdateStockRevertLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewUpdateStockRevertLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateStockRevertLogic {
	return &UpdateStockRevertLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *UpdateStockRevertLogic) UpdateStockRevert(in *product.UpdateStockReq) (*product.BaseMsg, error) {
	logrus.Info(fmt.Sprintf("UpdateStockRevert UpdateStockReq: %+v", in))

	if len(in.Data) == 0 {
		return &product.BaseMsg{}, nil
	}

	var skuIds []uint64
	stockMap := make(map[uint64]uint32)
	for _, v := range in.Data {
		if v.Id > 0 && v.Stock > 0 {
			skuIds = append(skuIds, v.Id)
			if stock, ok := stockMap[v.Id]; !ok {
				stockMap[v.Id] = v.Stock
			} else {
				stockMap[v.Id] = stock + v.Stock
			}
		}
	}

	if len(skuIds) == 0 {
		return &product.BaseMsg{}, nil
	}

	// 获取子事务屏障对象
	barrier, err := dtmgrpc.BarrierFromGrpc(l.ctx)
	if err != nil {
		return nil, resultx.StatusError(resultx.DTM_ERROR, err.Error())
	}

	// 开启子事务屏障
	err = barrier.CallWithDB(l.svcCtx.DB, func(tx *sql.Tx) error {
		var mods []qm.QueryMod
		mods = append(mods, model.ProductVariationMetumWhere.ProductID.IN(skuIds))
		mods = append(mods, model.ProductVariationMetumWhere.MetaKey.EQ("_stock"))
		list, err := model.ProductVariationMeta(mods...).All(l.ctx, tx)
		if err != nil {
			if err == sql.ErrNoRows {
				return resultx.StatusError(resultx.PRODUCT_NO_VALID_VARIATION_ID, "")
			}

			return err
		}

		if len(list) == 0 {
			return resultx.StatusError(resultx.PRODUCT_NO_VALID_VARIATION_ID, "")
		}

		for _, v := range list {
			if stock, ok := stockMap[v.ProductID]; ok {
				var info MetaInfo
				err = queries.Raw(fmt.Sprintf(
					`update %s set %s=%s+%d where %s="%d"`,
					model.TableNames.ProductVariationMeta,
					model.ProductVariationMetumColumns.MetaValue,
					model.ProductVariationMetumColumns.MetaValue,
					stock,
					model.ProductVariationMetumColumns.MetaID,
					v.MetaID,
				)).Bind(l.ctx, tx, &info)

				if err != nil {
					logrus.Info(fmt.Sprintf("UpdateStockRevert queries.Raw err: %+v", err))
				} else {
					logrus.Info(fmt.Sprintf("UpdateStockRevert queries.Raw info: %+v", info))
				}
			}
		}

		return nil
	})

	if err != nil {
		return nil, err
	}

	return &product.BaseMsg{
		Msg: i18n.UpdateSuccess,
	}, nil
}
